package cn.tedu.store.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.tedu.store.entity.Address;
import cn.tedu.store.entity.District;
import cn.tedu.store.mapper.AddressMapper;
import cn.tedu.store.service.IAddressService;
import cn.tedu.store.service.IDistrictService;
import cn.tedu.store.service.ex.AccessDeniedException;
import cn.tedu.store.service.ex.AddressNotFoundException;
import cn.tedu.store.service.ex.AddressSizeLimitException;
import cn.tedu.store.service.ex.DeleteException;
import cn.tedu.store.service.ex.InsertException;
import cn.tedu.store.service.ex.UpdateException;

/**
 * 收货地址业务层实现类型
 * 
 * @author DELL
 *
 */
@Service
public class AddressServiceImpl implements IAddressService {

	@Autowired
	private AddressMapper addressMap;
	
	@Autowired
	private IDistrictService service;

	@Override
	public void addnew(Address address, Integer uid, String username) {
		// 通过uid 获取收货地址的数量
		Integer count = countByUid(uid);
		// 判断数量是否超过了最大上限的限制
		if (count >= MAX_COUNT) {
			// 是:抛出AddressSizeLimitExcpetion
			throw new AddressSizeLimitException("收货地址已超出上限范围！");
		}
		// 判断收货地址的数量是否为0
		// 是:即将增加的收货地址是默认的 isDefault=1
		// 否:即将增加的收货地址不是默认的 isDefault=0
		Integer isDefault = count == 0 ? 1 : 0;

		// 补全数据: 将isDefault封装到参数address中
		address.setIsDefault(isDefault);
		// 补全数据:将参数uid封装到参数address中
		address.setUid(uid);
		// 补全数据:将参数username封装为参数address中的createUser和modifiedUser属性值
		address.setCreatedUser(username);
		address.setModifiedUser(username);
		// 补全数据:创建当前时间对象,封装为参数address中的createTime和modifiedTime属性值
		address.setCreatedTime(new Date());
		address.setModifiedTime(new Date());
		//补全数据：省市区的名称
		 District province = service.getByCode(address.getProvinceCode());
		 if(province != null) {
			 address.setProvinceName(province.getName());
		 }
		District city = service.getByCode(address.getCityCode());
		if(city != null) {
			address.setCityName(city.getName());
		}
		District area = service.getByCode(address.getAreaCode());
		if(area != null) {
			address.setAreaName(area.getName());
		}
		
		// 执行插入数据,并获取返回值
		 insert(address);

	}
	
	/**
	 * 查询某用户的收货地址列表
	 * @param uid 用户id
	 * @return 该用户的收货地址列表
	 */
	@Override
	public List<Address> getByUid(Integer uid) {
		
		return addressMap.findByUid(uid);
	}
	
	@Transactional
	@Override
	public void setDefault(Integer aid, Integer uid, String username) {
		//根据参数aid查询收货地址数据
		Address result = findByAid(aid);
		//判断查询结果是否为null
		if(result == null) {
			//是  抛出 AddressNotFoundException
			throw new AddressNotFoundException("收货地址不存在！");
		}
		//判断uid是否是相同归属问题
		if(!result.getUid().equals(uid)){
			//否  抛出 AccessDeniedException 归属问题异常
			throw new AccessDeniedException("归属问题");
		}
		//将当前说有收货地址设置为非默认
		System.err.println("准备执行 setDefault() 中的    updateNonDefault(uid)方法");
		updateNonDefault(uid);
		System.err.println("执行完毕 setDefault() 中的    updateNonDefault(uid)方法!!!");
		//将当前选中的收货地址设置为默认
		updateDefault(aid, username, new Date());
		
	}

	@Override
	@Transactional
	public void delete(Integer aid, Integer uid, String username) {
		//查询参数aid是否存在
		Address result = findByAid(aid);
		//判断信息是否为空  是 则 抛出异常
		if(result == null) {
			throw new AddressNotFoundException("地址信息不存在！");
		}
		//判断uid数据和参数 uid是否匹配
		if(!result.getUid().equals(uid)) {
			throw new AccessDeniedException("归属问题异常！");
		}
		//执行删除
		 deleteAddress(aid);
		
		//判断删除的数据is_defualt是否为0
		if(result.getIsDefault() == 0) {
			return;
		}
		
		//如果是删除的是默认is_defualt是1 则执行以下操作！
		
		// 以下分析是多余的：
	    // 调用countByUid(uid)统计当前用户的收货地址数量
			Integer count = countByUid(uid);
	    // 判断数量是否为0
			if(count == 0) {
				// 当前用户已经没有收货地址，可直接结束：return;
				return;
			}
	    // 调用findLastModified(uid)找出最后修改的收货地址
			Address modified = findLastModified(uid);
			System.err.println("modified" + modified.getAid());
	    // 基于以上查询结果中的aid，将该收货地址设置为默认，并获取返回值
			updateDefault(modified.getAid(),username, new Date());
	    
	}
	
	
	
	
	
	
	/**
	 * 插入收货地址数据
	 * @param address 收货地址数据
	 */
	private void insert(Address address) {
		Integer rows = addressMap.insert(address);
		if (rows != 1) {
			throw new InsertException("增加收货地址数据时出现未知错误");
		}
	}
	
	/**
	 * 根据收货地址数据的id删除收货地址
	 * @param aid 收货地址数据的id
	 */
	private void deleteAddress(Integer aid) {
		Integer rows = addressMap.deleteAddress(aid);
		if (rows != 1) {
			throw new DeleteException("删除收货地址数据时出现未知错误");
		}
	}
	
	/**
	 * 将指定的收货地址设置为默认
	 * @param aid 收货地址数据的id
	 * @param modifiedUser 修改执行人
	 * @param modifiedTime 修改时间
	 */
	private void updateDefault(Integer aid, String modifiedUser, Date modifiedTime) {
		Integer rows = addressMap.updateDefault(aid, modifiedUser, modifiedTime);
		System.err.println("aid : "+aid+"  rows: "+rows );
		if (rows != 1) {
			throw new UpdateException("更新数据时出现未知错误[2]");
		}
	}
	
	/**
	 * 将某用户的所有收货地址设置为非默认
	 * @param uid 用户id
	 */
	private void updateNonDefault(Integer uid) {
		Integer rows = addressMap.updateNonDefault(uid);
		System.err.println("uid : "+uid+"  rows: "+rows );
		if (rows < 1) {
			throw new UpdateException("更新数据时出现未知错误[1]");
		}
	}
	
	
	/**
	 * 根据用户id统计该用户的收货地址数据的数量
	 * @param uid 用户id
	 * @return 该用户的收货地址数据的数量
	 */
	private Integer countByUid(Integer uid) {
		return addressMap.countByUid(uid);
	}
	
	
	/**
	 * 根据收货地址数据的id查询收货地址详情
	 * @param aid 收货地址数据的id
	 * @return 匹配的收货地址详情，如果没有匹配的数据，则返回null
	 */
	private Address findByAid(Integer aid) {
		return addressMap.findByAid(aid);
	}
	
	
	/**
	 * 查询某用户最后修改1条收货地址
	 * @param uid 用户的id
	 * @return 该用户的最后修改1条收货地址
	 */
	private Address findLastModified(Integer uid) {
		return addressMap.findLastModified(uid);
	}

	@Override
	public Address getByAid(Integer aid) {
		Address address = findByAid(aid);
		if(address == null) {
			throw new AddressNotFoundException("收货地址不存在！");
		}
		address.setCreatedUser(null);
		address.setCreatedTime(null);
		address.setModifiedUser(null);
		address.setModifiedTime(null);
		
		
		return address;
	}

}
